# -*-coding:utf-8-*-

'''
在Py中 一切皆为对象
面向对象编程 -- 面向过程编程 面向函数编程
面向过程编程 一组函数顺序执行，为了简化程序设计， 把函数切分成子函数，降低系统复杂度
面向对象编程  把程序看做是一组对象的集合 程序的执行，就是一系列消息在各个对象之间传递

类（class）  可以把类看做是模板（工厂）
实例（instance） 根据模板创建出来的一个个对象，
    汽车： 类，建造汽车的图纸（模板、工厂）
          实例对象  开的车
属性：表示这类东西具有的特征
方法：表示这类东西可以做的事情
'''

# 面向过程编程表示汽车
# car1 = {'brand':'bmw','age':1}

# 用class 来定义，（object）来表示这个类继承 object类
# class Car(object):
#     pass

# 定义属性和方法
# class Car:
#
#     def __init__(self,brand,age):
#         self.brand = brand
#         self.age = age
#
#     def brok(self):
#         print('刹车了')
#
#     def add(self):
#         print('在加速了')

'''
__init() 初始函数，在创建一个对象实例的时候默认被调用，不需要手动调用，
所有我们用来初始化一些属性

self 表示创建的实例本身  self.brand = brand 就把属性绑定到了我们创建的这个实例上
                        表示这个实例有属性brand，并且它的值就是外部传过来的
                        
brok（）中的self 表示对象实例本身,在py中要想使用instance.method()这样格式工作
                必须在class里面定义method的时候，必须把参数的第一个位置给留出来
                用来指代未来调用这个
实例.broke（） 实例.add（） 

'''

# car1 = Car('BMW',1)
# print(car1.brand)
# print(car1.age)
# car1.brok()
# car1.add()
#
# car2 = Car('audi',3)
# car2.max_speed = 120
# print(car2.brand)
# print(car2.age)
# car2.brok()
# car2.add()
# print(car2.max_speed)
'''
定义一个person类，属性 name age height 方法 eat cry walk

医生： 职称 方法  看病
患者：病名       求医
'''
class Person:

     def __init__(self,age,name,height):
         self.name = name
         self.age = age
         self.height = height

     def eat(self):
         print(f'{self.name}-{self.age}-{self.height} eating')

     def cry(self):
         print(f'{self.name}-{self.age}-{self.height} crying')

     def walk(self):
         print(f'{self.name}-{self.age}-{self.height} walking')

# person = Person(name='liu',age=12,height=188)
# person.eat()
# person.cry()
# person.walk()
# class Doctor(Person):
#
#         def __init__(self,name,age,height,perssion):
#             # Person.__init__(name,age,height)  # 选其一
#             super.__init__(name,age,height)
#             self.perssion = perssion
#
#         def way(self):
#             print('chi yao')
#         def kanbing(self):
#             print('kanbing')
# class Patients(Person):
#     def __init__(self,name,age,height,paname):
#         Person.__init__(name,age,height)
#         self.paname = paname
#     def spatients(self):
#         print('qiuyi')





'''
封装: 区分内外
    外面的人看不见里面的东西，但里面的人可以看见 ---封装的主要用意
    requests.get('baidu.com')
    我们定义类本身，就是一种封装的思想，去调用car2.broke ,就实现了汽车的刹车动作，但我们不能看到
    内部是如何实现的
    
    封装的事项还体现在 封装的属性 内部可以直接调用，外部不能直接调用，但我们可以通过其他方式
    如定义get接口访问-- 提高安全性。
    
    另外，PY中还有使用 单下划线和双下划线的方法来隐藏属性
    

'''
# class Car:
#
#     def __init__(self,name,age):
#         self.__name = name
#         self._age = age
#
#     def get_name(self):
#         print(f'I m {self.__name}')
#
#     def get_age(self):
#         print(f'i m {self._age} years old')
#
# car = Car('bmw',12)
# print(car._age)
# # 不可以直接从外部调用  得通过
# print(car._Car__name)
# # 或者通过内部属性调用
# car.get_name()
# car.get_age()

'''
继承: 当类之间有很大的相似的功能，我们可以提前这些共同的功能作为基类（父类），其他的类直接调用基类就好
     calss:mini_car(Car)
        pass
    mini_car:子类，派生类
    Car：父类，基类，超类

'''
# class Car:
#
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#
#     def get_name(self):
#         print(f'I m {self.name}')
#
#     def get_age(self):
#         print(f'i m {self.age} years old')
'''不想在类中添加任何其他的属性或者方法'''
# class mini_car(Car):
#     pass
#
# car1 = mini_car('bmw',12)
# print(car1.name)
# print(car1.age)
# car1.get_name()
# car1.get_age()

'''如果有新的属性，新的方法，对原有方法有不同实现'''
# class mini_car(Car):
#
#     def __init__(self,name,age,max_speed):
#         Car.__init__(self,name,age)
#         self.max_speed = max_speed
#     # 定义新方法
#     def show_speed(self):
#         print(f'i can run {self.max_speed} fast')
#     # 重构原方法
#     def get_age(self):
#         print('hahha')
#
# car1 = mini_car('audi',12,100)
# print(car1.name)
# print(car1.age)
# print(car1.max_speed)
# car1.show_speed()
# car1.get_age()
'''内置函数 issubclass 判断是否是其子类'''
# print(issubclass(mini_car,Car))

''' python 支持多重继承        !!!!!不建议多用  '''
# class A:
#     def aa(self):
#         print('a')
# class B:
#     def bb(self):
#         print('b')
#
# class C(A,B):
#     pass
#
# c = C()
# c.aa()
# c.bb()
# '''内置属性 bases 打印父类'''
# print(C.__bases__)

'''
多态：多种状态，不同的对象，调用同一接口，表现出不同的状态，就称为多态
    多态满足条件
    1，继承：多态必须发生在父类与子类之间
    2.重写：子类必须重写分类的方法
'''
# class Car:
#     def who(self):
#         print('i m a car')
# class Boat:
#     def who(self):
#         print('i m a boat')
# class Fly():
#     def who(self):
#         print('i m a fly')
#
#
# class trans:
#     def who(self):
#         print('i m a tool')
# class Car(trans):
#     def who(self):
#         print('i m a car')
# class Boat(trans):
#     def who(self):
#         print('i m a boat')
# class Fly(trans):
#     def who(self):
#         print('i m a fly')

'''一个接口  多重实现'''
# def func(obj):
#     obj.who()
#
# car = Car()
# boat = Boat()
# fly = Fly()
#
# func(car)
# func(boat)
# func(fly)

'''
类变量：所有实例共享的
实例变量:用于每一个实例的唯一数据
'''
# class Dog:
#     kind = 'animal'
#
#     def __init__(self,name):
#         self.name = name
# dog1 = Dog('fff')
# dog2 = Dog('ccc')

'''如果类变量是可变'''
# class Dog:
#     food = []
#
#     def __init__(self,name):
#         self.name = name
#
# dog1 = Dog('fff')
# dog2 = Dog('fff')
# dog1.food.append('water')
# print(dog2.food)
# dog2.food.append('meat')
# print(dog1.food)
# print(Dog.food)

'''同样的变量名 同时出现在实例和类属性中 优先查找实例变量'''
# class Dog:
#     kind = 'animal'
#     name = 'dog'
# dog1 = Dog()
# dog1.name = 'mike'
# print(dog1.name)

'''定义 一个类，要实现能计数（实例化了几个对象）'''
# class A:
#     count = 0
#     def __init__(self):
#         A.count += 1
# a = A()
# print(A.count)
# b = A()
# print(A.count)

'''
类方法：可以由类对象和实例对象调用，并且第一个参数都是cls,使用装饰器@classmethod
        是将类本身作为对象进行操作的方法
实例方法：只能由实例调用，并且第一个参数都是self
静态方法：可由类对象或实例对象调用，方法中不能使用类和实例的任何属性和方法，使用@staticmethod
        
'''
# 实例方法
# class Func:
#     def instanc_func(self):
#         print('实例方法')
#     @classmethod
#     def class_func(cls):
#         print('类方法')
#     @staticmethod
#     def statc_func():
#         print('静态方法')
# # 实例对象，3种方法都可以调用
# func = Func()
# func.instanc_func()
# func.class_func()
# func.statc_func()
#
# # 类对象不能调用实例方法
# Func.class_func()
# Func.statc_func()
# Func.instanc_func()

'''
使用场景
    类方法：方法中只涉及到 类变量的方法
'''
# class Car:
#     max_speed = 100
#
#     @classmethod
#     def modify_speed(cls,num):
#         cls.max_speed += num
#
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
# car1 = Car('bmw',12)
# car2 = Car('audi',34)
# Car.modify_speed(20)
#
# print(car1.max_speed)
# print(car2.max_speed)
'''
静态方法 既不需要传入self,也不需要cls,这使得调用静态方法不能获得类中定义的属性和其他方法，
        也就是说，我们调回静态方法不会影响类队形 或实例对象的状态
        静态方法有点赋予与类对象的工具
'''
class Person():
    kind = 'human'

    def __init__(self,name):
        self.name = name

    @staticmethod
    def print_message():
        print('create a person')

class three:

    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c

    def get_toal(self):
        return self.a + self.b + self.c

    @staticmethod
    def judge(a,b,c):
        if a+b >c and a+c>b and b+c>a:
            return True

if three.judge(10.21,31):
    s = three(10,20,30)